package cn.tradewin.advisor.persist.services.impl;

import java.util.List;

import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;

import cn.tradewin.advisor.exceptions.DBException;
import cn.tradewin.advisor.persist.mapper.AccountMapper;
import cn.tradewin.advisor.persist.mapper.PermissionsMapper;
import cn.tradewin.advisor.persist.mapper.RolePermsMapper;
import cn.tradewin.advisor.persist.mapper.RolesMapper;
import cn.tradewin.advisor.persist.mapper.UserPermsMapper;
import cn.tradewin.advisor.persist.mapper.UserRolesMapper;
import cn.tradewin.advisor.persist.mapper.UsersMapper;
import cn.tradewin.advisor.persist.model.AccountPerm;
import cn.tradewin.advisor.persist.model.Permissions;
import cn.tradewin.advisor.persist.model.RolePermsKey;
import cn.tradewin.advisor.persist.model.Roles;
import cn.tradewin.advisor.persist.model.UserPermsKey;
import cn.tradewin.advisor.persist.model.UserRolesKey;
import cn.tradewin.advisor.persist.model.Users;
import cn.tradewin.advisor.persist.services.AdvisorSecurityService;

public class AdvisorSecurityServiceImpl implements AdvisorSecurityService {

	private final SqlSessionFactory sqlSessionFactory;
	
	public AdvisorSecurityServiceImpl(SqlSessionFactory sqlSessionFactory) {
		this.sqlSessionFactory = sqlSessionFactory;
	}
	
	/** 
	 * find the Role through the specified role id.
	 */
	public Roles findRole(String id) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolesMapper mapper = session.getMapper(RolesMapper.class);
			return mapper.selectByPrimaryKey(Integer.parseInt(id));
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	/**
	 * add role to Roles table
	 */
	public int addRole(Roles role) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolesMapper mapper = session.getMapper(RolesMapper.class);
			int iCount = mapper.insert(role);
			if (iCount < 0) {
				session.rollback();
				return iCount;
			}
			session.commit();
			return  iCount;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	/**
	 * update role for Roles table master
	 */
	public int updRole(Roles role) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolesMapper mapper = session.getMapper(RolesMapper.class);
			int iCount = mapper.updateByPrimaryKey(role);
			if (iCount < 0) {
				session.rollback();
				return iCount;
			}
			session.commit();
			return iCount;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	/**
	 * get all roles information from roles master table
	 */
	public List<Roles> listAllRoles()  throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolesMapper mapper = session.getMapper(RolesMapper.class);
			return mapper.selectByExample(null);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	public Permissions findPerm(String id) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			PermissionsMapper mapper = session.getMapper(PermissionsMapper.class);
			return mapper.selectByPrimaryKey(Integer.parseInt(id));
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	
	/**
	 * add permission to permission master table
	 */
	public int addPerm(Permissions perm) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			PermissionsMapper mapper = session.getMapper(PermissionsMapper.class);
			int iCount = mapper.insert(perm);
			if (iCount < 0) {
				session.rollback();
				return iCount;
			}
			session.commit();
			return  iCount;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	/**
	 * update permission master table
	 */
	public int updPerm(Permissions perm) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			PermissionsMapper mapper = session.getMapper(PermissionsMapper.class);
			int iCount = mapper.updateByPrimaryKey(perm);
			if (iCount < 0) {
				session.rollback();
				return iCount;
			}
			session.commit();
			return  iCount;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	public List<Permissions> listAllPerms()  throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			PermissionsMapper mapper = session.getMapper(PermissionsMapper.class);
			return mapper.selectByExample(null);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	public Users getUser(String id) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UsersMapper mapper = session.getMapper(UsersMapper.class);
			return mapper.selectByPrimaryKey(id);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public List<Permissions> getAuthorizedPermsForRole(String roleId) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolePermsMapper mapper = session.getMapper(RolePermsMapper.class);
			return mapper.selectAuthorizedPermsForRole(roleId);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public List<Permissions> getAvailablePermsForRole(String roleId)
			throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolePermsMapper mapper = session.getMapper(RolePermsMapper.class);
			return mapper.selectAvailablePermsForRole(roleId);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public int addPermToRole(String roleId, String permId) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolePermsMapper mapper = session.getMapper(RolePermsMapper.class);
			RolePermsKey key = new RolePermsKey();
			key.setRoleId(Integer.valueOf(roleId));
			key.setPermId(Integer.valueOf(permId));
			int count = mapper.insert(key);
			if (count < 0) {
				session.rollback();
				return count;
			}
			session.commit();
			return count;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public int removePermFromRole(String roleId, String permId)
			throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolePermsMapper mapper = session.getMapper(RolePermsMapper.class);
			RolePermsKey key = new RolePermsKey();
			key.setRoleId(Integer.valueOf(roleId));
			key.setPermId(Integer.valueOf(permId));
			int count = mapper.deleteByPrimaryKey(key);
			if (count < 0) {
				session.rollback();
				return count;
			}
			session.commit();
			return count;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	// assign permissions to account
	@Override
	public List<AccountPerm> getAuthorizedPermsForAccount(String id) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserPermsMapper mapper = session.getMapper(UserPermsMapper.class);
			return mapper.selectAuthorizedPermsForAccount(id);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public List<Permissions> getAvailablePermsForAccount(String id)
			throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserPermsMapper mapper = session.getMapper(UserPermsMapper.class);
			return mapper.selectAvailablePermsForAccount(id);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	@Override
	public int addPermToAccount(String id, String permId) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserPermsMapper mapper = session.getMapper(UserPermsMapper.class);
			UserPermsKey key = new UserPermsKey();
			key.setUserId(id);
			key.setPermId(Integer.valueOf(permId));
			int count = mapper.insert(key);
			if (count < 0) {
				session.rollback();
				return count;
			}
			session.commit();
			return count;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public int removePermFromAccount(String id, String permId)
			throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserPermsMapper mapper = session.getMapper(UserPermsMapper.class);
			UserPermsKey key = new UserPermsKey();
			key.setUserId(id);
			key.setPermId(Integer.valueOf(permId));
			int count = mapper.deleteByPrimaryKey(key);
			if (count < 0) {
				session.rollback();
				return count;
			}
			session.commit();
			return count;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	// assign role to specified account
	@Override
	public List<Roles> getAssignedRolesForAccount(String id) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserRolesMapper mapper = session.getMapper(UserRolesMapper.class);
			return mapper.selectAssignedRolesForAccount(id);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public List<Roles> getAvailableRolesForAccount(String id)
			throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserRolesMapper mapper = session.getMapper(UserRolesMapper.class);
			return mapper.selectAvailableRolesForAccount(id);
		} catch (Exception e) {
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}
	
	@Override
	public int addRoleToAccount(String id, String roleId) throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserRolesMapper mapper = session.getMapper(UserRolesMapper.class);
			UserRolesKey key = new UserRolesKey();
			key.setUserId(id);
			key.setRoleId(Integer.valueOf(roleId));
			int count = mapper.insert(key);
			if (count < 0) {
				session.rollback();
				return count;
			}
			session.commit();
			return count;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public int removeRoleFromAccount(String id, String roleId)
			throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			UserRolesMapper mapper = session.getMapper(UserRolesMapper.class);
			UserRolesKey key = new UserRolesKey();
			key.setUserId(id);
			key.setRoleId(Integer.valueOf(roleId));
			int count = mapper.deleteByPrimaryKey(key);
			if (count < 0) {
				session.rollback();
				return count;
			}
			session.commit();
			return count;
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public int getMaxRoleId() throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			RolesMapper mapper = session.getMapper(RolesMapper.class);
			return mapper.getMaxRoleId();
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

	@Override
	public int getMaxPermId() throws DBException {
		SqlSession session = null;
		try {
			session = sqlSessionFactory.openSession();
			PermissionsMapper mapper = session.getMapper(PermissionsMapper.class);
			return mapper.getMaxPermId();
		} catch (Exception e) {
			session.rollback();
			throw new RuntimeException(e.getMessage());
		} finally {
			if (session != null) {
				session.close();
			}
		}
	}

//	@Override
//	public int removeAllPermsFromAccount(String id) throws DBException {
//		SqlSession session = null;
//		try {
//			int count = 0;
//			session = sqlSessionFactory.openSession();
//			UserRolesMapper mapper = session.getMapper(UserRolesMapper.class);
//			count = mapper.deleteRolesFromUser(id);
//			UserPermsMapper permsMapper = session.getMapper(UserPermsMapper.class);
//			count = permsMapper.deletePermsFromUser(id);
//			UsersMapper userMapper = session.getMapper(UsersMapper.class);
//			count = userMapper.deleteByPrimaryKey(id);
//			AccountMapper accountMapper = session.getMapper(AccountMapper.class);
//			count = accountMapper.deleteByPrimaryKey(id);
//			session.commit();
//			return count;
//		} catch (Exception e) {
//			if (session != null) {
//				session.rollback();
//			}
//			throw new RuntimeException(e.getMessage());
//		} finally {
//			if (session != null) {
//				session.close();
//			}
//		}
//	}
}